Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustdoc: Reduce allocations in a theme function #95909

Merged
merged 1 commit into from
Apr 12, 2022
Merged

rustdoc: Reduce allocations in a theme function #95909

merged 1 commit into from
Apr 12, 2022

Conversation

vacuus
Copy link
Contributor

@vacuus vacuus commented Apr 10, 2022

str::replace allocates a new String...

This could probably be made more efficient, but I think it'd have to be clunky imperative code to achieve that.

@rustbot rustbot added the T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. label Apr 10, 2022
@rust-highfive
Copy link
Collaborator

r? @GuillaumeGomez

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 10, 2022
@GuillaumeGomez
Copy link
Member

I'm really not sure it'll change anything considering how rare this code is run. However, could you benchmark this locally and show us the results please? Running a perf check on this wouldn't show anything unfortunately...

@vacuus
Copy link
Contributor Author

vacuus commented Apr 11, 2022

For what it's worth, Godbolt reports fewer assembly language instructions for processing the string when compiled with -C opt-level=3. What should I be benchmarking? Do I need a specific tool/command? (Never done much benchmarking for anything before, sorry)

@GuillaumeGomez
Copy link
Member

You have a book on how to run benchmarks in rust here. So pick whichever you prefer. ;)

As for what do compare: take both codes (before and after your change) and run them on a string similar to the rustdoc CSS files (or on the rustdoc CSS files directly, doesn't matter). Once done, please provide the results alongside the source code for the benchmark as well.

@vacuus
Copy link
Contributor Author

vacuus commented Apr 11, 2022

I did the benchmarks very crudely by running cargo bench multiple times and estimating the range with the bulk of the times. Still, I think it's clear that there's a relative difference. I only changed the remove calls and not the join call for the benchmark because, for some reason, I couldn't get Cargo to use nightly*. I don't think intersperse/collect could ever be slower than collect/join, though, at least for any meaningful input.

ayu:  src/librustdoc/html/static/css/themes/ayu.css (631 lines)
dark: src/librustdoc/html/static/css/themes/dark.css (498 lines)
light: src/librustdoc/html/static/css/themes/light.css (464 lines)

current:
    dark: 109 μs
    light: 104-106 μs
    ayu: 140-150 μs
this PR (without the intersperse/collect):
    dark: 81-90 μs
    light: 77-80 μs
    ayu: 104-109 μs
use criterion::{black_box, criterion_group, criterion_main, Criterion};

pub fn criterion_benchmark(c: &mut Criterion) {
    // don't mind the naming of the benchmarks
    let mut group = c.benchmark_group("dark theme");
    // the string literal being the text of the file
    group.bench_function("new", |b| b.iter(|| new(black_box([string literal].to_string()))));
    group.finish();
}

fn old(s: String) -> String {
    s
        .trim()
        .replace('\n', " ")
        .replace('\t', " ")
        .replace('/', "")
        .replace('{', "")
        .replace('}', "")
        .split(' ')
        .filter(|s| !s.is_empty())
        .collect::<Vec<&str>>()
        .join(" ")
}

fn new(s: String) -> String {
    s
        .trim()
        .chars()
        .filter_map(|c| match c {
            '\n' | '\t' => Some(' '),
            '/' | '{' | '}' => None,
            c => Some(c),
        })
        .collect::<String>()
        .split(' ')
        .filter(|s| !s.is_empty())
        .collect::<Vec<&str>>()
        .join(" ")
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

*I tried:

  • cargo +nightly bench; Cargo gave an error saying that it's not a valid subcommand
  • Making a rust-toolchain.toml
  • Overriding rustup to use nightly in the directory (rustup show displays nightly as the active toolchain too)

@GuillaumeGomez
Copy link
Member

rustup install nightly && rustup default nightly in case you want the default toolchain to be nightly. However, cargo +nightly bench should work if nightly is installed, weird...

In any case, thanks for the results, it's really great!

I'll put it in the rollup since it's in a code location where the perf change won't have any impact on the results.

@bors: r+ rollup

@bors
Copy link
Contributor

bors commented Apr 11, 2022

📌 Commit 7feb738 has been approved by GuillaumeGomez

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 11, 2022
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Apr 12, 2022
…eGomez

rustdoc: Reduce allocations in a `theme` function

`str::replace` allocates a new `String`...

This could probably be made more efficient, but I think it'd have to be clunky imperative code to achieve that.
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 12, 2022
…askrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang#95320 (Document the current MIR semantics that are clear from existing code)
 - rust-lang#95722 (pre-push.sh: Use python3 if python is not found)
 - rust-lang#95881 (Use `to_string` instead of `format!`)
 - rust-lang#95909 (rustdoc: Reduce allocations in a `theme` function)
 - rust-lang#95910 (Fix crate_type attribute to not warn on duplicates)
 - rust-lang#95920 (use `Span::find_ancestor_inside` to get right span in CastCheck)
 - rust-lang#95936 (Fix a bad error message for `relative paths are not supported in visibilities` error)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 2836143 into rust-lang:master Apr 12, 2022
@rustbot rustbot added this to the 1.62.0 milestone Apr 12, 2022
@vacuus vacuus deleted the theme-build-rule branch April 12, 2022 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants